package cn.kgc.blogweb.controller;

import cn.kgc.blogcommon.pojo.Category;
import cn.kgc.blogcommon.pojo.News;
import cn.kgc.blogcommon.pojo.Type;
import cn.kgc.blogweb.api.CountApi;
import cn.kgc.blogweb.service.BlogService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
public class BlogController {

    //跨服务器查询用户名,解决方案
    //1.两个service，每个service有独立的Feign
    //2.写两个API

    @Autowired
    private BlogService blogService;

    @Autowired
    private CountApi countApi;

    @RequestMapping("/all_news")
    public String index(Integer categoryId, Integer typeId, Integer flag, Model model){
        Integer cid = categoryId == null ? 0 : categoryId;
        Integer tid = typeId == null ? 0 : typeId;
        flag = flag == null ? 0 : flag;
        List<Category> categoryList = new ArrayList<>();
        if(flag == 0){
            categoryList = blogService.getPopularCategory();
            cid = categoryList.get(0).getCategoryId();
        } else if (flag == 1) {
            categoryList = blogService.getCategoryByTypeId(tid);
            cid = categoryList.get(0).getCategoryId();
        } else if (flag == 2) {
            if(tid == 0){
                categoryList = blogService.getPopularCategory();
            } else {
                categoryList = blogService.getCategoryByTypeId(tid);
            }
        }
        List<News> allNews = blogService.getAllNews(cid);
        List<Type> allType = blogService.getAllType();
        long currentTime = System.currentTimeMillis();
        for(News news : allNews){
            long diff = currentTime - news.getCreateDate().getTime();
            long day = diff/(3600*24*1000) - 1;
            long hour = diff/(3600*1000) - 24;
            long minute = diff/(60*1000) - 60;
            if(day >= 1){
                news.setTimeAgo(day + "天前");
            } else if (hour < 24){
                news.setTimeAgo(hour + "小时前");
            } else if (minute < 60){
                news.setTimeAgo(minute + "分钟前");
            }
        }
        List<News> hotNews = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();
        String newsStr = countApi.getHot("hotNews");
        try {
            hotNews = mapper.readValue(newsStr, List.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        model.addAttribute("hotNews", hotNews);
        model.addAttribute("allType", allType);
        model.addAttribute("allNews", allNews);
        model.addAttribute("categoryList", categoryList);
        model.addAttribute("cid", cid);
        model.addAttribute("tid", tid);

        if(allNews.size() != 0){
            //浏览量
            StringBuilder builder = new StringBuilder();
            for (News news : allNews) {
                if (builder.length() > 0) {
                    builder.append(",");
                }
                builder.append(news.getNewsId());
            }
            //获取所有文章的浏览量
            Map<Integer, Integer> map = countApi.getAllCounts(builder.toString());
            //将浏览量加入文章中
            for (News news : allNews) {
                news.setReadNum(map.get(news.getNewsId()));
            }
        }
        return "index";
    }

    @RequestMapping("/get_news")
    public String getNewsById(Integer newsId, Integer typeId, HttpServletRequest request, Model model){
        Integer tid = typeId == null ? 0 : typeId;
        List<Type> allType = blogService.getAllType();
        String ipAddr = getIp(request);//获取远程的ip地址
        Integer count = countApi.addOneAddress(newsId, ipAddr);
        News news = blogService.getNewsById(newsId);
        news.setReadNum(count);

        List<News> hotNews = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();
        String newsStr = countApi.getHot("hotNews");
        try {
            hotNews = mapper.readValue(newsStr, List.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        model.addAttribute("news", news);
        model.addAttribute("allType", allType);
        model.addAttribute("hotNews", hotNews);
        model.addAttribute("tid", tid);
        return "news";
    }

    public static String getIp(HttpServletRequest request){
        //代理进来，则透过防火墙获取真实IP地址
        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        //如果没有代理，则获取真实ip
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }

    //24小时热闻
    @Scheduled(cron = "0 0/30 * * * ?")
    public void getHotNews(){
        System.out.println("进入定时器方法.....");
        //1.获取数据库中24小时内新闻id
        List<Integer> newsIdList = blogService.getMinId();
        //2.在Redis中从此id开始读取所有的hyperlog键的值
        List<Integer> sortedNews = countApi.getHotNews(newsIdList);
        List<News> newsMapping = blogService.getHotNews(sortedNews);
        //映射实体类
        List<News> hotNews = new ArrayList<>();
        for(int i = 0;i<sortedNews.size();i++){
            Integer newsId = sortedNews.get(i);
            for(int j = 0;j<newsMapping.size();j++){
                if(newsId == newsMapping.get(j).getNewsId()){
                    hotNews.add(newsMapping.get(j));
                }
            }
        }
        //实体类设置浏览量
        StringBuilder builder = new StringBuilder();
        for(News news : hotNews){
            if (builder.length() > 0) {
                builder.append(",");
            }
            builder.append(news.getNewsId());
        }
        Map<Integer, Integer> allCounts = countApi.getAllCounts(builder.toString());
        for(News news : hotNews){
            news.setReadNum(allCounts.get(news.getNewsId()));
        }
        //3.加入z  set排序更新热闻列表后清空zset
        long delResult = countApi.zSetRemove("hotList");
        ObjectMapper mapper = new ObjectMapper();
        String hotNewsJSON = "";
        try {
            hotNewsJSON = mapper.writeValueAsString(hotNews);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        countApi.setHot("hotNews", hotNewsJSON);
    }

}
